package com.globallogic.javatrainings.sergiiivanov.model;

import java.io.Serializable;

import com.globallogic.javatrainings.sergiiivanov.resources.ErrorCodes;

/**
 * Implements students management<br>
 * Works with internal collection of Student and provides functionality for
 * managing the collection and individual entities<br>
 * Used in University as students member
 * 
 * @author Sergey
 * @see University#students
 */
public class StudentsManager implements Serializable, NameUniqueObserver {

    private static final long serialVersionUID = 1L;
    private MyArray<Student> students;

    /**
     * default constructor
     */
    public StudentsManager() {
        students = new MyArray<Student>(new Student[0]);
    }

    /**
     * Adds new student into collection
     * 
     * @param name
     *            - valid name; not null, not empty, unique in the collection
     * @param mobile
     *            - free string
     * @param email
     *            - free string
     * @throws UniversityWarning
     *             name is not valid
     */
    public void addPerson(String name, String mobile, String email) throws UniversityWarning {
        if (null == name || Const.STRING_EMPTY.equals(name)) {
            throw new UniversityWarning(ErrorCodes.PERSON_NAME_NULL);
        }
        Student student = new Student();
        student.addObserver(this);
        student.setName(name);
        student.setMobile(mobile);
        student.setEmail(email);

        students.add(student);
    }

    /**
     * @return count of students in collection added by
     *         {@link #addPerson(String, String, String)}
     */
    public int countStudents() {
        return students.size();
    }

    /**
     * Returns {@link Student} stored under provided index in collection
     * 
     * @param index
     *            valid index ( 0 < index < {@link #countStudents()} )
     * @return {@link Student}
     * @throws UniversityWarning
     *             wrong index
     * @throws UniversityFailure
     *             code is broken
     */
    public Student getStudentByIndex(int index) throws UniversityWarning, UniversityFailure {
        if (index < 0 || countStudents() <= index) {
            throw new UniversityWarning(ErrorCodes.ARRAY_INDEX_IS_OUT_OF_BOUNDARIES);
        }
        return students.get(index);
    }

    /**
     * @return copy of students collection as {@link MyArray} of {@link Student}
     */
    public MyArray<Student> getStudents() {
        return students.copy();
    }

    /**
     * Throws UniversityWarning when name is found in the collection of stored
     * students
     * 
     * @param name
     *            for validation
     * @throws UniversityWarning
     *             when name was found
     */
    @Override
    public void hasDuplicates(String name) throws UniversityWarning {
        if (name != null) {
            for (MyArrayToNamesCovertable existingOne : students) {
                if (name.equals(existingOne.getName()))
                    throw new UniversityWarning(ErrorCodes.PERSON_NAME_NOT_UNIQUE + name);
            }
        }
    }

    /**
     * Clears all student links by calling {@link Student#removeLinks()} and
     * removes student
     * 
     * @param s
     *            {@link Student} to remove
     * @throws UniversityWarning
     *             student not found or null
     * @throws UniversityFailure
     *             code is broken
     */
    public void removeStudent(Student s) throws UniversityWarning, UniversityFailure {
        if (s == null || students.indexOf(s) < 0)
            throw new UniversityWarning(ErrorCodes.STUDENT_NOT_FOUND);
        if (s != null)
            s.removeLinks();
        students.remove(s);
    }
}
